package com.xms.logging.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xms.core.data.Entity;
import com.xms.core.enums.OperationType;
import com.xms.logging.data.EntitylogMapper;
import com.xms.logging.entity.EntityLog;
import com.xms.logging.entity.EntityLogChangeData;
import com.xms.schema.entity.Attribute;
import com.xms.schema.extension.AttributeExt;
import com.xms.sdk.core.OwnerObject;
import com.xms.sdk.extensions.EntityWrapper;
import com.xms.security.identity.ICurrentUser;
import com.xms.utils.JsonUtil;
import com.xms.utils.StringUtil;
import com.xms.utils.UUIDUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author migo
 * @since 2021-08-29
 */
@Service
public class EntityLogService extends ServiceImpl<EntitylogMapper, EntityLog> implements IEntityLogService {
    private ICurrentUser _currentUser;

    @Autowired
    public EntityLogService(ICurrentUser currentUser) {
        _currentUser = currentUser;
    }

    @Override
    public boolean createdLog(Entity data, com.xms.schema.entity.Entity entityMetadata, List<Attribute> attributeMetadatas) {
        if (!entityMetadata.getLogenabled()) {
            return false;
        }
        EntityLog entity = new EntityLog();
        entity.setEntityid(entityMetadata.getEntityid());
        entity.setEntitylogid(UUIDUtil.get());
        entity.setOperationtype(OperationType.Create.value());
        entity.setUserid(_currentUser.getUser().SystemUserId);
        entity.setOrganizationid(_currentUser.getUser().OrganizationId);
        entity.setRecordid(data.getIdValue());
        entity.setAttributemask(StringUtil.join(data.keySet().toArray(), ","));
        entity.setCreatedon(LocalDateTime.now());
        List<EntityLogChangeData> datas = new ArrayList<>();
        EntityLogChangeData changeData = new EntityLogChangeData();
        changeData.name = data.getIdName();
        changeData.original = "";
        changeData.value = data.getIdValue().toString();
        datas.add(changeData);
        /*Iterator iterator = data.entrySet().iterator();
        while(iterator.hasNext())
        {
            Map.Entry entry = (Map.Entry)iterator.next();
            String key = entry.getKey().toString();
            Object value = entry.getValue();
            Attribute attr = attributeMetadatas.stream().filter(n -> n.getName().equalsIgnoreCase(key)).findFirst().get();
            if (!key.equalsIgnoreCase("createdon") && !key.equalsIgnoreCase("createdby")
                    && !key.equalsIgnoreCase("modifiedon") && !key.equalsIgnoreCase("modifiedby")
                    && !key.equalsIgnoreCase("versionnumber") && !key.equalsIgnoreCase("organizationid")) {
                if (attr != null && (AttributeExt.typeIsText(attr) || AttributeExt.typeIsNText(attr))) {
                    continue;
                }
                EntityLogChangeData changeData = new EntityLogChangeData();
                changeData.name = key;
                changeData.original = "";
                changeData.value = value != null ? value.toString() : "";
                datas.add(changeData);
            }
        }*/
        entity.setChangedata(JsonUtil.toJSONString(datas));
        return super.save(entity);
    }

    @Override
    public boolean updatedLog(Entity originData, Entity newData, com.xms.schema.entity.Entity entityMetadata, List<Attribute> attributeMetadatas) {

        if (!entityMetadata.getLogenabled()) {
            return false;
        }
        EntityLog entity = new EntityLog();
        entity.setEntityid(entityMetadata.getEntityid());
        entity.setEntitylogid(UUIDUtil.get());
        entity.setOperationtype(OperationType.Update.value());
        entity.setUserid(_currentUser.getUser().SystemUserId);
        entity.setOrganizationid(_currentUser.getUser().OrganizationId);
        entity.setRecordid(newData.getIdValue());
        entity.setAttributemask(StringUtil.join(newData.keySet().toArray(), ","));
        entity.setCreatedon(LocalDateTime.now());
        List<EntityLogChangeData> datas = new ArrayList<>();
        Iterator iterator = newData.entrySet().iterator();
        while(iterator.hasNext())
        {
            Map.Entry entry = (Map.Entry)iterator.next();
            String key = entry.getKey().toString();
            String value = entry.getValue() != null ? entry.getValue().toString() : "";
            String originValue = originData.containsKey(key) ? (originData.get(key) != null ? originData.get(key).toString() : "") : "";
            if (!originValue.equalsIgnoreCase(value)) {
                Attribute attr = attributeMetadatas.stream().filter(n -> n.getName().equalsIgnoreCase(key)).findFirst().get();
                //if(attr == null || !attr.getLogenabled()) continue;
                if (!key.equalsIgnoreCase("createdon") && !key.equalsIgnoreCase("createdby")
                        && !key.equalsIgnoreCase("modifiedon") && !key.equalsIgnoreCase("modifiedby")
                        && !key.equalsIgnoreCase("versionnumber") && !key.equalsIgnoreCase("organizationid")) {
                    if (attr != null && (AttributeExt.typeIsText(attr) || AttributeExt.typeIsNText(attr))) {
                        continue;
                    }
                    EntityLogChangeData changeData = new EntityLogChangeData();
                    changeData.name = key;
                    changeData.original = originValue;
                    changeData.value = value;
                    datas.add(changeData);
                }
            }
        }
        entity.setChangedata(JsonUtil.toJSONString(datas));
        return super.save(entity);
    }

    @Override
    public boolean deletedLog(Entity data, com.xms.schema.entity.Entity entityMetadata, List<Attribute> attributeMetadatas) {
        if (!entityMetadata.getLogenabled()) {
            return false;
        }
        EntityLog entity = new EntityLog();
        entity.setEntityid(entityMetadata.getEntityid());
        entity.setEntitylogid(UUIDUtil.get());
        entity.setOperationtype(OperationType.Delete.value());
        entity.setUserid(_currentUser.getUser().SystemUserId);
        entity.setOrganizationid(_currentUser.getUser().OrganizationId);
        entity.setRecordid(data.getIdValue());
        entity.setAttributemask(StringUtil.join(data.keySet().toArray(), ","));
        entity.setCreatedon(LocalDateTime.now());
        List<EntityLogChangeData> datas = new ArrayList<>();
        Iterator iterator = data.entrySet().iterator();
        while(iterator.hasNext())
        {
            Map.Entry entry = (Map.Entry)iterator.next();
            String key = entry.getKey().toString();
            String value = entry.getValue() != null ? entry.getValue().toString() : "";
            if (!key.equalsIgnoreCase("versionnumber")) {
                Attribute attr = attributeMetadatas.stream().filter(n -> n.getName().equalsIgnoreCase(key)).findFirst().get();
                //if(attr == null || !attr.getLogenabled()) continue;
                if (attr != null && (AttributeExt.typeIsText(attr) || AttributeExt.typeIsNText(attr))) {
                    continue;
                }
                EntityLogChangeData changeData = new EntityLogChangeData();
                changeData.name = key;
                changeData.original = value;
                changeData.value = "";
                datas.add(changeData);
            }
        }
        entity.setChangedata(JsonUtil.toJSONString(datas));
        return super.save(entity);
    }

    @Override
    public boolean sharedLog(Entity data, com.xms.schema.entity.Entity entityMetadata) {
        if (!entityMetadata.getLogenabled()) {
            return false;
        }
        EntityLog entity = new EntityLog();
        entity.setEntityid(entityMetadata.getEntityid());
        entity.setEntitylogid(UUIDUtil.get());
        entity.setOperationtype(OperationType.Share.value());
        entity.setUserid(_currentUser.getUser().SystemUserId);
        entity.setOrganizationid(_currentUser.getUser().OrganizationId);
        entity.setRecordid(data.getIdValue());
        entity.setCreatedon(LocalDateTime.now());
        return super.save(entity);
    }

    @Override
    public boolean assignedLog(Entity data, OwnerObject from, OwnerObject to, com.xms.schema.entity.Entity entityMetadata) {
        if (!entityMetadata.getLogenabled()) {
            return false;
        }
        EntityLog entity = new EntityLog();
        entity.setEntityid(entityMetadata.getEntityid());
        entity.setEntitylogid(UUIDUtil.get());
        entity.setOperationtype(OperationType.Assign.value());
        entity.setUserid(_currentUser.getUser().SystemUserId);
        entity.setOrganizationid(_currentUser.getUser().OrganizationId);
        entity.setRecordid(data.getIdValue());
        entity.setCreatedon(LocalDateTime.now());
        List<EntityLogChangeData> datas = new ArrayList<>();
        EntityLogChangeData changeData = new EntityLogChangeData();
        changeData.name = "ownerid";
        changeData.original = JsonUtil.toJSONString(from);
        changeData.value = JsonUtil.toJSONString(to);
        entity.setChangedata(JsonUtil.toJSONString(datas));
        return super.save(entity);
    }

    @Override
    public boolean mergedLog(Entity merged, Entity target, com.xms.schema.entity.Entity entityMetadata, List<Attribute> attributeMetadatas) {
        if (!entityMetadata.getLogenabled()) {
            return false;
        }
        EntityLog entity = new EntityLog();
        entity.setEntityid(entityMetadata.getEntityid());
        entity.setEntitylogid(UUIDUtil.get());
        entity.setOperationtype(OperationType.Assign.value());
        entity.setUserid(_currentUser.getUser().SystemUserId);
        entity.setOrganizationid(_currentUser.getUser().OrganizationId);
        entity.setRecordid(target.getIdValue());
        entity.setAttributemask(StringUtil.join(target.keySet().toArray(), ","));
        entity.setCreatedon(LocalDateTime.now());
        List<EntityLogChangeData> datas = new ArrayList<>();
        Iterator iterator = target.entrySet().iterator();
        while(iterator.hasNext())
        {
            Map.Entry entry = (Map.Entry)iterator.next();
            String key = entry.getKey().toString();
            String value = entry.getValue() != null ? entry.getValue().toString() : "";
            String originValue = merged.containsKey(key) ? (merged.get(key) != null ? merged.get(key).toString() : "") : "";
            if (!originValue.equalsIgnoreCase(value)) {
                Attribute attr = attributeMetadatas.stream().filter(n -> n.getName().equalsIgnoreCase(key)).findFirst().get();
                //if(attr == null || !attr.getLogenabled()) continue;
                if (!key.equalsIgnoreCase("createdon") && !key.equalsIgnoreCase("createdby")
                        && !key.equalsIgnoreCase("modifiedon") && !key.equalsIgnoreCase("modifiedby")
                        && !key.equalsIgnoreCase("versionnumber")) {
                    if (attr != null && (AttributeExt.typeIsText(attr) || AttributeExt.typeIsNText(attr))) {
                        continue;
                    }
                    EntityLogChangeData changeData = new EntityLogChangeData();
                    changeData.name = key;
                    changeData.original = originValue;
                    changeData.value = value;
                    datas.add(changeData);
                }
            }
        }
        entity.setChangedata(JsonUtil.toJSONString(datas));
        return super.save(entity);
    }

    @Override
    public void clear() {
        super.remove(null);
    }

    @Override
    public void clear(UUID entityId) {
        super.remove(new LambdaQueryWrapper<EntityLog>().eq(EntityLog::getEntityid, entityId));
    }
}
